﻿/*
 * Created by SharpDevelop.
 * User: Administrator
 * Date: 3/1/2011
 * Time: 8:30 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using TomatoSynchronizer.Entities;
using TomatoSynchronizer.Store;
using HtmlAgilityPack;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;

namespace TomatoSynchronizer.Synchronizer
{
	/// <summary>
	/// Description of ArticleCategorySynchronizer
	/// </summary>
	public static class ArticleCategorySynchronizer
	{
		public static void Synchronize(Site siteSrc,Site siteDest,HtmlWeb client,SyncDirection direction)
		{
			switch(direction)
			{
				case SyncDirection.Download:
					UpLoadItems(siteDest,siteSrc,client,direction);
					break;
				case SyncDirection.Upload:
					UpLoadItems(siteSrc,siteDest,client,direction);
					break;
				case SyncDirection.DownloadAndUpload:
					UpLoadItems(siteDest,siteSrc,client,SyncDirection.Download);
					UpLoadItems(siteSrc,siteDest,client,SyncDirection.Upload);
					break;
				case SyncDirection.UploadAndDownload:
					UpLoadItems(siteSrc,siteDest,client,SyncDirection.Upload);
					UpLoadItems(siteDest,siteSrc,client,SyncDirection.Download);
					break;
				case SyncDirection.Synchronize:
//					ArticleCategoryStore ArticleCategoryStoreDest = new ArticleCategoryStore(siteDest,client);
//					ArticleCategoryStoreDest.Truncate();
					
					MappingStore mappingSrc = UpLoadItems(siteSrc,siteDest,client,SyncDirection.Upload);
					
					ArticleCategoryStore ArticleCategoryStoreDest = new ArticleCategoryStore(siteDest,client);
					var categories = ArticleCategoryStoreDest.DownloadItems();
					
					foreach(ArticleCategory category in categories)
					{
						bool sync = false;
						
						foreach(Mapping mapping in mappingSrc.Mappings)
						{
							if(mapping.DestValue == category.articles_categories_id)
							{
								sync = true;
							}
						}	
						
						if(!sync)
						{
							if(!ArticleCategoryStoreDest.DeleteItem(category.articles_categories_id))
							{
								throw new Exception("Could not delete the ArticleCategory " + category.articles_categories_name + " in site " + ArticleCategoryStoreDest.site.Name);
							}
						}
					}
					break;
			}
		}
		
		private static MappingStore UpLoadItems(Site _siteSrc,Site _siteDest,HtmlWeb client,SyncDirection direction)
		{
			ArticleCategoryStore ArticleCategoryStoreSrc = new ArticleCategoryStore(_siteSrc,client);
			ArticleCategoryStore ArticleCategoryStoreDest = new ArticleCategoryStore(_siteDest,client);
			
			ArticleCategory[] ArticleCategoryesSrc =  ArticleCategoryStoreSrc.LoadItems();
			ArticleCategory[] ArticleCategoryesDest =  ArticleCategoryStoreDest.LoadItems();
			
			MappingStore mappingStoreSrc = new MappingStore(_siteSrc,_siteDest,"articles_categories_id");
			MappingStore mappingStoreDest = new MappingStore(_siteDest,_siteSrc,"articles_categories_id");
			
			mappingStoreSrc.Clean<ArticleCategory>(ArticleCategoryStoreSrc,ArticleCategoryStoreDest);
			mappingStoreDest.Clean<ArticleCategory>(ArticleCategoryStoreDest,ArticleCategoryStoreSrc);
			
			MappingStore mappingStore = new MappingStore(_siteSrc,_siteDest,"languages_id");
			
			List<ArticleCategory> alreadySynchronized = new List<ArticleCategory>();
			
			foreach(ArticleCategory ArticleCategorySrc in ArticleCategoryesSrc)
			{
				//we assume the ArticleCategory is not yet synchronized
				bool synchronized = false;
				
				//we check if a mapping already exists for this ArticleCategory in the destination store
				foreach(Mapping mapping in mappingStoreSrc.Mappings)
				{
					if(mapping.SrcValue == ArticleCategorySrc.articles_categories_id && synchronized == false)
					{
						if(!string.IsNullOrEmpty(mapping.DestValue))
						{
							//this ArticleCategory already exists in the destination store
							//we check if everything changed since the last synchronization
							ArticleCategory ArticleCategoryDest = ArticleCategoryStoreDest.GetItem(mapping.DestValue);
							if(!string.IsNullOrEmpty(ArticleCategoryDest.articles_categories_id))
							{
								synchronized = SynchronizeItem(ArticleCategorySrc,ArticleCategoryDest);
							}
							else
							{
								//the mapping exists, but the ArticleCategory has been deleted in the destination store
								//we set a flag that this mapping does not exists anymore
								mapping.Exists = false;
							}
						}
					}
				}
				
				if(!synchronized)
				{
					//there is no mapping, we check if this ArticleCategory already exists in the destination store
					foreach(ArticleCategory ArticleCategoryDest in ArticleCategoryesDest)
					{
						foreach(Mapping mapping in mappingStore.Mappings)
						{
							try
							{
								if(ArticleCategorySrc.articles_categories_names["articles_categories_name[" + mapping.SrcValue + "]"] == ArticleCategoryDest.articles_categories_names["articles_categories_name[" + mapping.DestValue + "]"] && synchronized == false && !alreadySynchronized.Contains(ArticleCategorySrc))
								{
									//we get the 2 currencies from sites to get sure they really exist
									ArticleCategory src = ArticleCategorySrc.Store.GetItem(ArticleCategorySrc.articles_categories_id);
									ArticleCategory dest = ArticleCategoryDest.Store.GetItem(ArticleCategoryDest.articles_categories_id);
									
									if(!string.IsNullOrEmpty(src.articles_categories_id))
									{
										if(!string.IsNullOrEmpty(dest.articles_categories_id))
										{
											Mapping _mapping = new Mapping(ArticleCategorySrc.articles_categories_id,ArticleCategoryDest.articles_categories_id,"articles_categories_id");
											mappingStoreSrc.Mappings.Add(_mapping);
											
											synchronized = SynchronizeItem(ArticleCategorySrc,ArticleCategoryDest);
										}
										else
										{
											synchronized = false;
										}
									}
									else
									{
										synchronized = true;
									}
								}
							}
							catch (KeyNotFoundException)
							{
								
							}
						}
						
					}
				}
				
				if(!synchronized)
				{
					//no mapping the ArticleCategory is new
					//we insert it in the destination store
					string remoteId = string.Empty;
					
					Dictionary<string, string> _articles_categories_names = new Dictionary<string, string>();
					Dictionary<string, string> _articles_categories_urls = new Dictionary<string, string>();
					Dictionary<string, string> _meta_descriptions = new Dictionary<string, string>();
					Dictionary<string, string> _meta_keywordss = new Dictionary<string, string>();
					Dictionary<string, string> _page_titles = new Dictionary<string, string>();
					
					foreach(Mapping mapping in mappingStore.Mappings)
					{
						_articles_categories_names["articles_categories_name[" + mapping.DestValue + "]"] = ArticleCategorySrc.articles_categories_names.ContainsKey("articles_categories_name[" + mapping.SrcValue + "]") ? ArticleCategorySrc.articles_categories_names["articles_categories_name[" + mapping.SrcValue + "]"] : "";
						_articles_categories_urls["articles_categories_url[" + mapping.DestValue + "]"] = ArticleCategorySrc.articles_categories_urls.ContainsKey("articles_categories_url[" + mapping.SrcValue + "]") ? ArticleCategorySrc.articles_categories_urls["articles_categories_url[" + mapping.SrcValue + "]"] : "";
						_meta_descriptions["meta_description[" + mapping.DestValue + "]"] =ArticleCategorySrc.meta_descriptions.ContainsKey("meta_description[" + mapping.SrcValue + "]") ? ArticleCategorySrc.meta_descriptions["meta_description[" + mapping.SrcValue + "]"] : "";
						_meta_keywordss["meta_keywords[" + mapping.DestValue + "]"] =ArticleCategorySrc.meta_keywordss.ContainsKey("meta_keywords[" + mapping.SrcValue + "]") ? ArticleCategorySrc.meta_keywordss["meta_keywords[" + mapping.SrcValue + "]"] : "";
						_page_titles["page_title[" + mapping.DestValue + "]"] = ArticleCategorySrc.page_titles.ContainsKey("page_title[" + mapping.SrcValue + "]") ? ArticleCategorySrc.page_titles["page_title[" + mapping.SrcValue + "]"] : "";
					}
					
					Dictionary<string, string> old_articles_categories_names = ArticleCategorySrc.articles_categories_names;
					Dictionary<string, string> old_articles_categories_urls = ArticleCategorySrc.articles_categories_urls;
					Dictionary<string, string> old_meta_descriptions = ArticleCategorySrc.meta_descriptions;
					Dictionary<string, string> old_meta_keywordss = ArticleCategorySrc.meta_keywordss;
					Dictionary<string, string> old_page_titles = ArticleCategorySrc.page_titles;
					
					ArticleCategorySrc.articles_categories_names = _articles_categories_names;
					ArticleCategorySrc.articles_categories_urls = _articles_categories_urls;
					ArticleCategorySrc.meta_descriptions = _meta_descriptions;
					ArticleCategorySrc.meta_keywordss = _meta_keywordss;
					ArticleCategorySrc.page_titles = _page_titles;
					
					remoteId = ArticleCategoryStoreDest.InsertItem(ArticleCategorySrc);
					
					synchronized = remoteId != string.Empty;
					
					if(!synchronized)
					{
						throw new Exception("The ArticleCategory " + ArticleCategorySrc.articles_categories_id + " has not been synchronized");
					}
					
					ArticleCategorySrc.articles_categories_names = old_articles_categories_names;
					ArticleCategorySrc.articles_categories_urls = old_articles_categories_urls;
					ArticleCategorySrc.meta_descriptions = old_meta_descriptions;
					ArticleCategorySrc.meta_keywordss = old_meta_keywordss;
					ArticleCategorySrc.page_titles = old_page_titles;
					
					Mapping _mapping = new Mapping(ArticleCategorySrc.articles_categories_id,remoteId,"articles_categories_id");
					mappingStoreSrc.Mappings.Add(_mapping);
					synchronized = true;
				}
				
				if(!synchronized)
				{
					throw new Exception("could not synchronize the ArticleCategory " + ArticleCategorySrc.articles_categories_id);
				}
				
				ArticleCategoryStoreSrc.PersistItem(ArticleCategorySrc);
				alreadySynchronized.Add(ArticleCategorySrc);
			}
			
			mappingStoreSrc.Save();		
			
			mappingStoreDest.Truncate();
			
			//we save the mappings in the destination MappingStore too
			foreach(Mapping mapping in mappingStoreSrc.Mappings)
			{
				if(mapping.Exists)
				{
					Mapping mappingDest = new Mapping(mapping.DestValue,mapping.SrcValue,mapping.Property);
					mappingStoreDest.Mappings.Add(mappingDest);
				}
			}
			
			mappingStoreDest.Save();
			
			//we check if the 2 MappingStore are synchronized
			if(mappingStoreSrc.Mappings.Count != mappingStoreDest.Mappings.Count)
			{
				throw new Exception("The mapping store are not synchronized");
			}
			
			return mappingStoreSrc;
		}
		
		private static bool SynchronizeItem(ArticleCategory ArticleCategorySrc,ArticleCategory ArticleCategoryDest)
		{
			bool synchronized = true;
			
			if(!ArticleCategorySrc.Equals(ArticleCategoryDest))
			{
				synchronized = false;
				
				//we update the destination ArticleCategory
				ArticleCategorySrc.language_id = ArticleCategoryDest.language_id;
				ArticleCategorySrc.articles_categories_id = ArticleCategoryDest.articles_categories_id;
				
				Dictionary<string, string> _articles_categories_names = new Dictionary<string, string>();
				Dictionary<string, string> _articles_categories_urls = new Dictionary<string, string>();
				Dictionary<string, string> _meta_descriptions = new Dictionary<string, string>();
				Dictionary<string, string> _meta_keywordss = new Dictionary<string, string>();
				Dictionary<string, string> _page_titles = new Dictionary<string, string>();
				
				var languages = ArticleCategoryDest.Store.site.GetLanguageStore().LoadItems();
				MappingStore mappingStore = new MappingStore(ArticleCategorySrc.Store.site,ArticleCategoryDest.Store.site,"languages_id");
				foreach(Mapping mapping in mappingStore.Mappings)
				{
					_articles_categories_names["articles_categories_name[" + mapping.DestValue + "]"] = ArticleCategorySrc.articles_categories_names["articles_categories_name[" + mapping.SrcValue + "]"];
					_articles_categories_urls["articles_categories_url[" + mapping.DestValue + "]"] = ArticleCategorySrc.articles_categories_urls["articles_categories_url[" + mapping.SrcValue + "]"];
					_meta_descriptions["meta_description[" + mapping.DestValue + "]"] = ArticleCategorySrc.meta_descriptions["meta_description[" + mapping.SrcValue + "]"];
					_meta_keywordss["meta_keywords[" + mapping.DestValue + "]"] = ArticleCategorySrc.meta_keywordss["meta_keywords[" + mapping.SrcValue + "]"];
					_page_titles["page_title[" + mapping.DestValue + "]"] = ArticleCategorySrc.page_titles["page_title[" + mapping.SrcValue + "]"];
				}
				
				Dictionary<string, string> old_articles_categories_names = ArticleCategorySrc.articles_categories_names;
				Dictionary<string, string> old_articles_categories_urls = ArticleCategorySrc.articles_categories_urls;
				Dictionary<string, string> old_meta_descriptions = ArticleCategorySrc.meta_descriptions;
				Dictionary<string, string> old_meta_keywordss = ArticleCategorySrc.meta_keywordss;
				Dictionary<string, string> old_page_titles = ArticleCategorySrc.page_titles;
				
				ArticleCategorySrc.articles_categories_names = _articles_categories_names;
				ArticleCategorySrc.articles_categories_urls = _articles_categories_urls;
				ArticleCategorySrc.meta_descriptions = _meta_descriptions;
				ArticleCategorySrc.meta_keywordss = _meta_keywordss;
				ArticleCategorySrc.page_titles = _page_titles;
				
				synchronized = ArticleCategoryDest.Store.UpdateItem(ArticleCategorySrc);
				
				ArticleCategorySrc.articles_categories_names = old_articles_categories_names;
				ArticleCategorySrc.articles_categories_urls = old_articles_categories_urls;
				ArticleCategorySrc.meta_descriptions = old_meta_descriptions;
				ArticleCategorySrc.meta_keywordss = old_meta_keywordss;
				ArticleCategorySrc.page_titles = old_page_titles;
			}
			
			return synchronized;
		}
		
		private static string UploadItem(ArticleCategoryStore ArticleCategoryStoreDest,ArticleCategory ArticleCategory)
		{
			string remoteId = string.Empty;
			
			remoteId = ArticleCategoryStoreDest.InsertItem(ArticleCategory);
			
			return remoteId;
		}
	}
}
